﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Sec_scan安全漏洞扫描系统_2._0.Services
{
    /// <summary>
    /// socks5代理连接
    /// </summary>
    public class Tl_Socks5_Services
    {
        private string _proxyHost;
        private int _proxyPort;

        public Tl_Socks5_Services()
        {
            // ip地址
            _proxyHost = Api.Socks5_Api.ip;
            // 端口
            _proxyPort = Api.Socks5_Api.port;
        }
        // 通过代理访问百度
        public async Task<string> AccessBaiduThroughProxy()
        {
            return await SendHttpRequestThroughProxy("www.baidu.com", 443, "/");
        }

        // 通过代理访问Google
        public async Task<string> AccessGoogleThroughProxy()
        {
            return await SendHttpRequestThroughProxy("www.google.com", 443, "/");
        }

        // 通过代理发送HTTP请求
        private async Task<string> SendHttpRequestThroughProxy(string host, int port, string path)
        {
            try
            {
                // 连接到SOCKS5代理服务器
                using (TcpClient proxyClient = new TcpClient())
                {
                    await proxyClient.ConnectAsync(_proxyHost, _proxyPort);
                    using (NetworkStream proxyStream = proxyClient.GetStream())
                    {
                        // SOCKS5握手 - 无需认证
                        await PerformSocks5Handshake(proxyStream);

                        // 发送连接请求到目标服务器
                        await SendSocks5ConnectRequest(proxyStream, host, port);

                        // 通过代理发送HTTP请求
                        return await SendHttpRequest(proxyStream, host, path);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"通过SOCKS5代理访问 {host} 失败: {ex.Message}", ex);
            }
        }
        // SOCKS5握手
        private async Task PerformSocks5Handshake(NetworkStream stream)
        {
            byte[] handshakeRequest = new byte[]
            {
            0x05, // SOCKS版本5
            0x01, // 认证方法数量
            0x00  // 认证方法：0x00无需认证
            };

            await stream.WriteAsync(handshakeRequest, 0, handshakeRequest.Length);

            byte[] handshakeResponse = new byte[2];
            await stream.ReadAsync(handshakeResponse, 0, handshakeResponse.Length);

            if (handshakeResponse[0] != 0x05 || handshakeResponse[1] != 0x00)
            {
                throw new Exception("SOCKS5握手失败");
            }
        }

        // 发送SOCKS5连接请求
        private async Task SendSocks5ConnectRequest(NetworkStream stream, string host, int port)
        {
            byte[] addressBytes = Encoding.ASCII.GetBytes(host);
            byte[] connectRequest = new byte[7 + addressBytes.Length];

            connectRequest[0] = 0x05; // SOCKS版本
            connectRequest[1] = 0x01; // 连接命令
            connectRequest[2] = 0x00; // 保留
            connectRequest[3] = 0x03; // 地址类型：域名
            connectRequest[4] = (byte)addressBytes.Length; // 域名长度
            Array.Copy(addressBytes, 0, connectRequest, 5, addressBytes.Length);

            // 端口号（大端序）
            connectRequest[5 + addressBytes.Length] = (byte)(port >> 8);
            connectRequest[6 + addressBytes.Length] = (byte)(port & 0xFF);

            await stream.WriteAsync(connectRequest, 0, connectRequest.Length);

            // 读取连接响应
            byte[] connectResponse = new byte[10];
            await stream.ReadAsync(connectResponse, 0, connectResponse.Length);

            if (connectResponse[1] != 0x00)
            {
                throw new Exception($"SOCKS5连接失败，错误代码: {connectResponse[1]}");
            }
        }

        // 发送HTTP请求
        private async Task<string> SendHttpRequest(NetworkStream stream, string host, string path)
        {
            string request = $"GET {path} HTTP/1.1\r\n" +
                            $"Host: {host}\r\n" +
                            "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\r\n" +
                            "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
                            "Connection: close\r\n" +
                            "\r\n";

            byte[] requestBytes = Encoding.UTF8.GetBytes(request);
            await stream.WriteAsync(requestBytes, 0, requestBytes.Length);

            // 读取响应
            using (MemoryStream memoryStream = new MemoryStream())
            {
                byte[] buffer = new byte[4096];
                int bytesRead;

                while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                {
                    await memoryStream.WriteAsync(buffer, 0, bytesRead);
                }

                return Encoding.UTF8.GetString(memoryStream.ToArray());
            }
        }
    }
}
